package com.zzzzzz.app.account.service;

import java.util.List;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Service;

import com.zzzzzz.app.account.NoSuchUserException;
import com.zzzzzz.app.account.dao.UserRoleDao;
import com.zzzzzz.app.account.model.bo.UserBo;
import com.zzzzzz.app.account.model.bo.UserRoleBo;
import com.zzzzzz.core.dao.search.SearchContainer;
import com.zzzzzz.core.exception.SystemException;
import com.zzzzzz.core.exception.ZzzzzzException;

@Service
public class UserRoleManager {

	@Resource
	private UserRoleDao userRoleDao;

	public void addAssociation(long userId, long roleId) throws SystemException {
		userRoleDao.addAssociation(userId, roleId);
	}

	public void removeAssociation(long userId, long roleId) throws SystemException {
		userRoleDao.removeAssociation(userId, roleId);
	}
	
	public void deleteByRoleId(long roleId) throws SystemException {
		userRoleDao.deleteByRoleId(roleId);
	}
	
	public List<UserBo> findCurrentRoleMembers(long roleId, boolean ascending, int start, int offset) throws SystemException {
		return userRoleDao.findCurrentRoleMembers(roleId, ascending, start, offset);
	}
	
	public List<UserBo> findAvailableRoleMembers(long roleId, boolean ascending, int start, int offset) throws SystemException {
		return userRoleDao.findAvailableRoleMembers(roleId, ascending, start, offset);
	}

	public int findCurrentRoleMembersCount(long roleId) throws SystemException {
		return userRoleDao.findCurrentRoleMembersCount(roleId);
	}

	public int findAvailableRoleMembersCount(long roleId) throws SystemException {
		return userRoleDao.findAvailableRoleMembersCount(roleId);
	}
	
	public SearchContainer findCurrentRoleMembers(long roleId, boolean ascending, int cur, String actionPrefixURL) throws SystemException {
		return findCurrentRoleMembers(roleId, ascending, cur, actionPrefixURL, SearchContainer.DEFAULT_ITEMS_PER_PAGE, SearchContainer.DEFAULT_NUM_DISPLAY_PAGES, SearchContainer.DEFAULT_NUM_EDGE_PAGES);
	}
	
	public SearchContainer findCurrentRoleMembers(long roleId, boolean ascending, int cur, String actionPrefixURL, int offset, int numDisplayPages, int numEdgePages) throws SystemException {
		int total = findCurrentRoleMembersCount(roleId);
		int start = calculateStart(cur, offset, total);
		List<UserBo> currentRoleMembers = findCurrentRoleMembers(roleId, ascending, start, offset);
		SearchContainer searchContainer = new SearchContainer(currentRoleMembers, total, cur, actionPrefixURL, offset, numDisplayPages, numEdgePages);
		return searchContainer;
	}
	
	public SearchContainer findAvailableRoleMembers(long roleId, boolean ascending, int cur, String actionPrefixURL) throws SystemException {
		return findAvailableRoleMembers(roleId, ascending, cur, actionPrefixURL, SearchContainer.DEFAULT_ITEMS_PER_PAGE, SearchContainer.DEFAULT_NUM_DISPLAY_PAGES, SearchContainer.DEFAULT_NUM_EDGE_PAGES);
	}
	
	public SearchContainer findAvailableRoleMembers(long roleId, boolean ascending, int cur, String actionPrefixURL, int offset, int numDisplayPages, int numEdgePages) throws SystemException {
		int total = findAvailableRoleMembersCount(roleId);
		int start = calculateStart(cur, offset, total);
		List<UserBo> availableRoleMembers = findAvailableRoleMembers(roleId, ascending, start, offset);
		SearchContainer searchContainer = new SearchContainer(availableRoleMembers, total, cur, actionPrefixURL, offset, numDisplayPages, numEdgePages);
		return searchContainer;
	}
	
	private int calculateStart(int cur, int offset, int total) {
		if(total == 0) {
			cur = 1;
		}else {
			cur = Math.min(cur, (int) Math.ceil((double) total/offset));
		}
		cur = Math.max(cur, 1);
		int start = (cur - 1) * offset;
		return start;
	}
	
	public UserRoleBo findCurrentUser() throws SystemException, ZzzzzzException {
		Subject currentUser = SecurityUtils.getSubject();
		Session session = currentUser.getSession();
		UserRoleBo userRoleBo = (UserRoleBo) session.getAttribute("currentUser");
		if(userRoleBo == null) {
			Long currentUserId = (Long) currentUser.getPrincipal();
			if( currentUserId != null ) {
				userRoleBo = findByUserId(currentUserId);
	    		session.setAttribute("currentUser", userRoleBo);
			}
		}
		return userRoleBo;
    }

	public UserRoleBo findByUserId(Long userId) throws NoSuchUserException, SystemException {
		return userRoleDao.findByUserId(userId);
	}
	
}
